package com.ar4j.test.domain;

import java.util.Collection;
import java.util.List;

import com.ar4j.ActiveRecord;
import com.ar4j.annotation.Column;
import com.ar4j.annotation.Ignored;
import com.ar4j.annotation.DynamicMethod;
import com.ar4j.annotation.NamedQueryMethod;
import com.ar4j.annotation.NativeSqlMethod;
import com.ar4j.annotation.Table;
import com.ar4j.annotation.Type;
import com.ar4j.type.DateWithoutMillis;
import com.ar4j.type.DateWithoutMillisTypeConverter;
import com.ar4j.type.EnumTypeConverter;

/**
 * Represents the primary test table
 */
@SuppressWarnings("serial")
@Table("`PRIMARY`")
public abstract class Primary implements ActiveRecord<Primary> {
  private Long id;
  private String code;
  
  @Column("description")
  private String descriptionValue;
  
  private Long longField;
  private Double doubleField;
  private String stringField;
  
  @Type(converterClass = EnumTypeConverter.class)
  private TestEnum enumField;
  
  @Type(converterClass = DateWithoutMillisTypeConverter.class)
  private DateWithoutMillis dateField;
  
  @Ignored
  private String nonReadWriteProperty;
  
  @DynamicMethod("code")
  public abstract Primary findByCodeWithAnnotations(String code);
  
  public abstract Primary findByCode(String code);
  
  @DynamicMethod("code")
  public abstract Primary findByCodeWithArrayParameter(String[] code);
  
  @DynamicMethod("descriptionValue")
  public abstract long countByDescriptionValueWithAnnotation(String description);
  
  public abstract long countByDescriptionValue(String description);
  
  @NativeSqlMethod(sqlQuery = "SELECT COUNT(*) FROM `PRIMARY` WHERE ID >= :min AND ID <= :max", bindVariables = { "min", "max" })
  public abstract long nativeSqlCount(Long min, Long max);
  
  @NamedQueryMethod(queryName = "PRIMARY_COUNT_BY_MIN_MAX", bindVariables = { "min", "max" })
  public abstract long namedQueryCount(Long min, Long max);
  
  @NativeSqlMethod(sqlQuery = "SELECT P.* FROM `PRIMARY` P WHERE ID = :byId", bindVariables = "byId")
  public abstract Primary nativeSqlSingleFind(Long byId);
  
  @NamedQueryMethod(queryName = "PRIMARY_FIND_BY_ID", bindVariables = "byId")
  public abstract Primary namedQuerySingleFind(Long byId);
  
  @NativeSqlMethod(sqlQuery = "SELECT P.* FROM `PRIMARY` P WHERE ID <= :byId", bindVariables = "byId")
  public abstract Collection<Primary> nativeSqlCollectionFind(Long byId);
  
  @NamedQueryMethod(queryName = "PRIMARY_COLLECTION_FIND_BY_ID", bindVariables = "byId")
  public abstract Collection<Primary> namedQueryCollectionFind(Long byId);
  
  public abstract boolean existsByCode(String code);
  
  @DynamicMethod("code")
  public abstract boolean existsByCodes(Collection<String> code);
  
  public abstract boolean existsByEnumField(Collection<TestEnum> enumValues);
  
  @NativeSqlMethod(sqlQuery = "SELECT (CASE WHEN COUNT(*) > 0 THEN 'Y' ELSE 'N' END) FROM `PRIMARY` WHERE ID >= :min AND ID <= :max", bindVariables = { "min", "max" })
  public abstract boolean nativeSqlExists(Long min, Long max);
   
  @NativeSqlMethod(sqlQuery = "SELECT * FROM `PRIMARY` WHERE ID = :someIdLikeParam", bindVariables = "someIdLikeParam")
  public abstract Primary findByNativeSqlWithUnknownParameter(Long someIdLikeParam);
  
  @DynamicMethod("code")
  public abstract int deleteByCode(String code);
  
  @DynamicMethod("code")
  public abstract int deleteByCodes(Collection<String> code);
  
  @NativeSqlMethod(sqlQuery = "DELETE FROM `PRIMARY` WHERE CODE = :code", bindVariables = "code", update = true)
  public abstract int nativeSqlDelete(String code);
  
  @NativeSqlMethod(sqlQuery = "DELETE FROM `PRIMARY` WHERE CODE = :code", bindVariables = "code", update = true)
  public abstract void nativeSqlDeleteVoidReturn(String code);
  
  @NamedQueryMethod(queryName = "PRIMARY_DELETE_BY_CODE", bindVariables = "code", update = true)
  public abstract int namedQueryDelete(String code);
  
  public abstract List<Primary> findAllByDateField(Collection<DateWithoutMillis> values);
  
  public Long getId() {
    return id;
  }
  
  public void setId(Long id) {
    this.id = id;
  }
  
  public String getCode() {
    return code;
  }
  
  public void setCode(String code) {
    this.code = code;
  }
  
  public String getDescriptionValue() {
    return descriptionValue;
  }

  public void setDescriptionValue(String descriptionValue) {
    this.descriptionValue = descriptionValue;
  }

  public Long getLongField() {
    return longField;
  }
  
  public void setLongField(Long longField) {
    this.longField = longField;
  }
  
  public Double getDoubleField() {
    return doubleField;
  }
  
  public void setDoubleField(Double doubleField) {
    this.doubleField = doubleField;
  }
  
  public String getStringField() {
    return stringField;
  }
  
  public void setStringField(String stringField) {
    this.stringField = stringField;
  }
  
  public TestEnum getEnumField() {
    return enumField;
  }
  
  public void setEnumField(TestEnum enumField) {
    this.enumField = enumField;
  }
  
  public DateWithoutMillis getDateField() {
    return dateField;
  }

  public void setDateField(DateWithoutMillis dateField) {
    this.dateField = dateField;
  }
  
  public String getNonReadWriteProperty() {
    return nonReadWriteProperty;
  }

  public void setNonReadWriteProperty(String nonReadWriteProperty) {
    this.nonReadWriteProperty = nonReadWriteProperty;
  }
  
  @Ignored
  public String getIgnoredString() {
    return "I am ignored :(";
  }
  
  @Ignored
  public void setAnotherIgnoredString(String anotherIgnoredString) {
    // NOTHING TO DO BUT BE...
  }
  
  public String arbitraryMethodThatReturnsCode() {
    return code;
  }
  
}